﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using AmazonServices;
using DataStore.Domain;
using UI.Controls.Popup;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Windows.Controls.Primitives;
using Infrastructure;
using System.Runtime.InteropServices;

namespace UI.Controls
{
    /// <summary>
    /// Interaction logic for UpdateDocFromWS.xaml
    /// </summary>
    public partial class UpdateDocFromWS : UserControl
    {
        readonly ParameterizedThreadStart threadParameters;
        Thread searchThread;
        static readonly object _sync = new object();
        

        PopUp progress;
        PopUp coverProgress;

        BookSearchResponse _foundBooks;
        List<AmazonBook> _availableBooks;

        public void CancelSearch()
        {
            if (searchThread != null)
            {
                searchThread.Abort();
            }
        }

        /// <summary>
        /// The selected Amazon book
        /// </summary>
        public AmazonBook Selected
        {
            get
            {
                return SearchResults.SelectedItem as AmazonBook;
            }
        }

        public UpdateDocFromWS()
        {
            InitializeComponent();

            threadParameters = new ParameterizedThreadStart(SearchWS);
            
        }

        void InitSearchThread()
        {
            CancelSearch();
            searchThread = new Thread(threadParameters)
                               {
                                   IsBackground = true,
                                   Name = "AmazonSearch",
                                   Priority = ThreadPriority.AboveNormal
                               };
        }


        private void Search_Click(object sender, RoutedEventArgs e)
        {
            InitSearchThread();
            progress.Show();

            SearchParameter parameter = new SearchParameter();
            parameter.Book = new Book()
                                 {
                                     Title = Title.Text
                                 };

            
            searchThread.Start(parameter);
        }

        public void SearchWS(object parameter)
        {
            var searchParameter = parameter as SearchParameter;

            Books bookService = new Books();

            _foundBooks = bookService.SearchParsed(searchParameter.Book, searchParameter.Page, ResponseGroup.ItemAttributes);
            if (_foundBooks != null)
            {
                _availableBooks = _foundBooks.Books;
                Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                                       (Action<List<AmazonBook>>)delegate(List<AmazonBook> books)
                                                            {
                                                                PageIndicator.DataContext = _foundBooks;
                                                                SearchResults.ItemsSource = books;
                                                                progress.Close();
                                                            },
                                       _availableBooks
                    );
            }
            else
            {
                progress.Close();
            }
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            progress = new PopUp(SearchResults);
            
            TextBlock text = new TextBlock();
            text.Text = "Searching...";
            text.TextAlignment = TextAlignment.Center;
            text.VerticalAlignment = VerticalAlignment.Stretch;
            text.HorizontalAlignment = HorizontalAlignment.Stretch;
            text.Foreground = Brushes.White;
            progress.Content.Children.Add(text);
        }

        private void SearchResults_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var book = SearchResults.SelectedItem as AmazonBook;
            // Book has already a cover
            if(book == null || (book.Cover != null && book.Cover.Count != 0))
            {
                return;
            }

            var selectedRow = SearchResults.GetSelectedRow();
            var columnCell = SearchResults.GetCell(selectedRow, 0);

            // Show download progress indicator in cell
            coverProgress = new PopUp(columnCell);
            // TODO refactor to own style sheet
            TextBlock text = new TextBlock()
            {
                Text = "Generating preview...",
                TextTrimming = TextTrimming.CharacterEllipsis,
                TextWrapping = TextWrapping.WrapWithOverflow,
                TextAlignment = TextAlignment.Center,
                VerticalAlignment = VerticalAlignment.Stretch,
                HorizontalAlignment = HorizontalAlignment.Stretch,
                Foreground = Brushes.White,
            };
            coverProgress.Content.Children.Add(text);
            coverProgress.Show();

            var selectedBook = (from b in _availableBooks.AsParallel()
                                where b == book
                                select b).FirstOrDefault();
            Parallel.Invoke(() => GetAmazonCover(selectedBook));
        }

        void GetAmazonCover(object book)
        {
            AmazonBook selectedBook = book as AmazonBook;

            Books bookService = new Books();
            var covers = bookService.GetImages(new[] { selectedBook.ASIN }, ResponseGroup.Images);

            lock (_sync)
            {
                // Return if cover already exists
                if (selectedBook.Cover != null && selectedBook.Cover.Count != 0)
                {
                    SearchResults.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                        (Action)delegate
                        {
                            // Close progress indicator
                            coverProgress.Close();
                        });
                    return;
                }

                // Update cover
                if (covers != null)
                {
                    SearchResults.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                        (Action<AmazonCovers>)delegate(AmazonCovers amazonCovers)
                        {
                            Cover cover = new Cover();
                            cover.Path = new Link()
                                             {
                                                 Location = LinkType.Online,
                                                 Uri = amazonCovers.Thumbnail,
                                             };
                            if (selectedBook.Cover == null)
                            {
                                selectedBook.Cover = new List<Cover>();
                            }
                            selectedBook.Cover.Add(cover);

                            SearchResults.Items.Refresh();
                            coverProgress.Close();
                        },
                        covers);
                }
                else
                {
                    SearchResults.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                        (Action)delegate
                        {
                            // Close progress indicator
                            coverProgress.Close();
                        });
                }
                
            }
        }

        private void PrevResultPage_Click(object sender, RoutedEventArgs e)
        {
            if (_foundBooks.ItemPage == 1) { return; }

            progress.Show();
            InitSearchThread();

            SearchParameter parameter = new SearchParameter();
            parameter.Book = new Book()
            {
                Title = Title.Text
            };
            parameter.Page = _foundBooks.ItemPage - 1;
                        
            searchThread.Start(parameter);
        }

        private void NextResultPage_Click(object sender, RoutedEventArgs e)
        {
            if(_foundBooks.ItemPage == _foundBooks.TotalPages) { return; }

            progress.Show();
            InitSearchThread();

            SearchParameter parameter = new SearchParameter();
            parameter.Book = new Book()
            {
                Title = Title.Text
            };
            parameter.Page = _foundBooks.ItemPage + 1;

            searchThread.Start(parameter);
        }








        private class SearchParameter
        {
            public SearchParameter()
            {
                Page = 1;
            }

            public Book Book { get; set; }
            public int Page { get; set; }
        }
    }

    
}
